package com.kamistoat.netty.bio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * BIO编程实例
 */
public class BIOServer {
    public static void main(String[] args) throws IOException {
        // 1. 创建一个线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        // 创建一个ServerSocket监听6666端口.
        // ServerSocket就是一个Socket监听器，和IO模型没有任何关系
        // new ServerSocket(port)  new ServerSocket(port, 请求队列最大长度)  new ServerSocket(port, 队列最大长, 映射本地IpAddr)
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务端启动");

        // 2. 如果有客户端链接则创建一个新线程与之通信
        while (true) {
            // 使用 ServerSocket.accept()阻塞式监听端口的连接请求
            // 当Socket没有新连接时会阻塞在这里，而不是在while循环内重试
            System.out.println("等待连接");
            final Socket accept = serverSocket.accept();
            System.out.println("监听到连接请求");
            // 线程池开辟一个新线程，用来处理该连接之后的所有IO
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    handler(accept);
                }
            });
        }
    }

    /**
     * 用于和客户端进行通讯的handler方法
     *
     * @param socket 与客户端连接的socket
     */
    private static void handler(Socket socket) {
        try {
            byte[] bytes = new byte[1024];
            // 规定socket接收数据的方式为InputStream
            InputStream inputStream = socket.getInputStream();
            System.out.println("允许发送数据");
            while (true){
                // read代表读取数据的长度，最大为bytes定义的长度，当InputStream中还存在数据时就会不停在While中read数据
                // 当InputStream中没有数据时即read的结果为0，会阻塞在read()方法前不断重试读取而不会将0抛出去
                System.out.println("reading");
                int read = inputStream.read(bytes);
                // read()方法重试时发现Socket已经断开连接时，则返回read为-1，退出while循环并关闭服务端的socket
                if(read != -1){
                    System.out.println(new String(bytes, 0, read));
                }else{
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                System.out.println("关闭连接");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
